package puzzle.common.imgreader;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import tomoto.draw.DrawUtil;
import tomoto.image.BufferedImageUtil;
import tomoto.io.FileUtil;
import tomoto.io.StreamUtil;

public class GenericImgReader {
	public static final Dimension CELLSIZE = new Dimension(16, 16);

	private ImgPattern[] m_patterns;
	private String m_dataSymbols;
	private String m_visibleSymbols;

	public GenericImgReader(ImgPattern[] patterns, String dataSymbols, String visibleSymbols) {
		m_patterns = patterns;
		m_dataSymbols = dataSymbols;
		m_visibleSymbols = visibleSymbols;
	}

	public void readImage(InputStream is, Appendable out, File verificationImageFile)
			throws IOException {
		BufferedImage img = (BufferedImage) ImageIO.read(is);
		int w = img.getWidth() / CELLSIZE.width;
		int h = img.getHeight() / CELLSIZE.height;
		int[] matchResult = new int[w * h];

		ImgMatcher.match(img, m_patterns, CELLSIZE, new Dimension(w, h), matchResult);

		output(out, matchResult, w, h);

		if (verificationImageFile != null) {
			BufferedImage verificationImg = drawVerificationImage(img, matchResult, w, h);
			String suffix = FileUtil.getSuffix(verificationImageFile.getName());
			ImageIO.write(verificationImg, suffix, verificationImageFile);
		}
	}

	protected void output(Appendable out, int[] result, int w, int h) throws IOException {
		for (int y = 0; y < h; y++) {
			for (int x = 0; x < w; x++) {
				int i = result[x + y * w];
				out.append(m_dataSymbols.charAt(i + 1));
			}
			out.append(StreamUtil.LINE_SEPARATOR);
		}
	}

	private BufferedImage drawVerificationImage(BufferedImage img, int[] matchResult, int w, int h)
			throws IOException {
		BufferedImage out = new BufferedImage(img.getWidth() + 1, img.getHeight() + 1,
				BufferedImage.TYPE_INT_RGB);
		BufferedImageUtil.copyRGB(img, out);

		Graphics2D g2 = (Graphics2D) out.getGraphics();
		g2.setFont(Font.decode("arial-bold-14"));
		g2.setXORMode(Color.RED);

		DrawUtil.drawGrid(g2, 0, 0, CELLSIZE.width, CELLSIZE.height, w, h);

		for (int y = 0; y < h; y++) {
			for (int x = 0; x < w; x++) {
				int i = matchResult[x + y * w];
				String symbol = m_visibleSymbols.substring(i + 1, i + 2);
				int x1 = x * CELLSIZE.width + 1;
				int y1 = y * CELLSIZE.width + 15;
				g2.drawString(symbol, x1, y1);
			}
		}
		g2.dispose();

		return out;
	}

	public BufferedImage[] createDistanceImage(InputStream is) throws IOException {
		BufferedImage[] result = new BufferedImage[m_patterns.length];
		BufferedImage img = (BufferedImage) ImageIO.read(is);
		for (int i = 0; i < m_patterns.length; i++) {
			result[i] = ImgMatcher.createDistanceImage(img, m_patterns[i]);
		}
		return result;
	}

}
